#include "stm32f4xx.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "console_usart.h"

static usart_rx_callback_t rx_callback;

static void usart_lowlever_init(uint32_t BaidRate) 
{
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
    
    USART_InitTypeDef USART_InitStructure;
    memset(&USART_InitStructure, 0, sizeof(USART_InitTypeDef));
    USART_InitStructure.USART_BaudRate = BaidRate;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    /* USART1外设TX引脚使能DMA传输 */
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

static void usart_pin_init(void) 
{
    GPIO_InitTypeDef GPIO_InitStructure;
    memset(&GPIO_InitStructure, 0, sizeof(GPIO_InitTypeDef));

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; 
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); 
}

static void nvic_init(void) 
{
    NVIC_InitTypeDef NVIC_InitStructure;
    memset(&NVIC_InitStructure, 0, sizeof(NVIC_InitTypeDef));
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
}

void usart_init(uint32_t BaidRate) 
{
    /* dma初始化 并配置DMA_IT_TC转运完成中断 未使能DMA*/
    usart_pin_init();   //串口引脚复用功能初始化  
    usart_lowlever_init(BaidRate);  //串口底层初始化
    nvic_init();        //配置串口中断 
}

void usart_recv_callback_register(usart_rx_callback_t cb)
{
    /* 入口参数为外部函数指针 ，将外部函数指针赋值当前usart文件作用域的函数指针 */
    rx_callback = cb;
}

void USART1_IRQHandler(void) 
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) 
    {
        uint8_t data = USART_ReceiveData(USART1);
        /* if传入的函数指针不为空 */
        if(rx_callback != NULL)
        {
            /* 将rx数据当作rx_callback函数参数 */
            rx_callback(data);
        }
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}

void usart_sendbyte(uint8_t data)
{
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);
    USART_SendData(USART1,data);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void usart_send_strpack(char* arr)
{
    for(uint16_t i = 0;arr[i]!=0;i++)
    {
        usart_sendbyte(arr[i]);
    }
}
